# RUN: llc -mattr=+sve -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
# RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+sve -start-before=prologepilog %s -o - | FileCheck %s --check-prefix=ASM
# RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+sve -start-before=prologepilog %s -filetype=obj -o %t
# RUN: llvm-objdump --dwarf=frames %t | FileCheck %s --check-prefix=UNWINDINFO
# RUN: rm -rf %t
#
# Test allocation and deallocation of SVE objects on the stack,
# as well as using a combination of scalable and non-scalable
# offsets to access the SVE on the stack.
#
# SVE objects are allocated below the (scalar) callee saves,
# and above spills/locals and the alignment gap, e.g.
#
#     +-------------+
#     | stack arg   |
#     +-------------+ <- SP before call
#     | Callee Saves|
#     | Frame record|       (if available)
#     |-------------| <- FP (if available)
#     |  SVE area   |
#     +-------------+
#     |/////////////| alignment gap.
#     |     :       |
#     | Stack objs  |
#     |     :       |
#     +-------------+ <- SP after call and frame-setup
#
--- |

  define void @test_allocate_sve() uwtable { entry: unreachable }
  define void @test_allocate_sve_gpr_callee_saves() uwtable { entry: unreachable }
  define void @test_allocate_sve_gpr_realigned() uwtable { entry: unreachable }
  define void @test_address_sve() uwtable { entry: unreachable }
  define void @test_address_sve_fp() uwtable { entry: unreachable }
  define void @test_stack_arg_sve() uwtable { entry: unreachable }
  define void @test_address_sve_out_of_range() uwtable { entry: unreachable }
  define void @test_address_gpr_vla() uwtable { entry: unreachable }
  define aarch64_sve_vector_pcs void @save_restore_pregs_sve() uwtable { entry: unreachable }
  define aarch64_sve_vector_pcs void @save_restore_zregs_sve() uwtable { entry: unreachable }
  define aarch64_sve_vector_pcs void @save_restore_sve() uwtable { entry: unreachable }
  define aarch64_sve_vector_pcs void @save_restore_sve_realign() uwtable { entry: unreachable }
  define aarch64_sve_vector_pcs void @frame_layout() uwtable { entry: unreachable }
  define void @fp_relative_index_with_float_save() uwtable { entry: unreachable }

...
# +----------+
# |scratchreg|  // x29 is used as scratch reg.
# +----------+
# | %stack.0 |  // scalable SVE object of n * 18 bytes, aligned to 16 bytes,
# |          |  // to be materialized with 2*ADDVL (<=> 2 * n * 16bytes)
# +----------+
# | %stack.1 |  // not scalable
# +----------+ <- SP

# CHECK-LABEL: name: test_allocate_sve
# CHECK:       stackSize: 32

# CHECK:      bb.0.entry:
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 32
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR

# ASM-LABEL: test_allocate_sve:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 16 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 16 * VG
# ASM:       .cfi_def_cfa wsp, 32
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

#
# UNWINDINFO:       DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT:  DW_CFA_offset: reg29 -16
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:       DW_CFA_def_cfa: reg31 +32
# UNWINDINFO:       DW_CFA_def_cfa_offset: +16
# UNWINDINFO:       DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT:  DW_CFA_restore: reg29


name:            test_allocate_sve
stack:
  - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2 }
  - { id: 1, stack-id: default, size: 16, alignment: 8 }
body:             |
  bb.0.entry:
    RET_ReallyLR
---
...
# +----------+
# | x20, x21 |  // callee saves
# |scratchreg|  // x29 is used as scratch reg.
# +----------+
# | %stack.0 |  // scalable objects
# +----------+
# | %stack.1 |  // not scalable
# +----------+ <- SP

# CHECK-LABEL: name: test_allocate_sve_gpr_callee_saves
# CHECK:       stackSize: 48

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 32
# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x20, $sp, 2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w20, -8
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w21, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -32
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22
#
# CHECK-NEXT: $x20 = IMPLICIT_DEF
# CHECK-NEXT: $x21 = IMPLICIT_DEF
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 48
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 32
# CHECK-NEXT: $x21, $x20 = frame-destroy LDPXi $sp, 2
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 32
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w20
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w21
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_allocate_sve_gpr_callee_saves:
# ASM:       .cfi_def_cfa_offset 32
# ASM:       .cfi_offset w20, -8
# ASM-NEXT:  .cfi_offset w21, -16
# ASM-NEXT:  .cfi_offset w29, -32
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 16 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 16 * VG
#
# ASM:       .cfi_def_cfa wsp, 48
# ASM:       .cfi_def_cfa_offset 32
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w20
# ASM-NEXT:  .cfi_restore w21
# ASM-NEXT:  .cfi_restore w29

#
# UNWINDINFO:       DW_CFA_def_cfa_offset: +32
# UNWINDINFO:       DW_CFA_offset: reg20 -8
# UNWINDINFO-NEXT:  DW_CFA_offset: reg21 -16
# UNWINDINFO-NEXT:  DW_CFA_offset: reg29 -32
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:       DW_CFA_def_cfa: reg31 +48
# UNWINDINFO:       DW_CFA_def_cfa_offset: +32
# UNWINDINFO:       DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT:  DW_CFA_restore: reg20
# UNWINDINFO-NEXT:  DW_CFA_restore: reg21
# UNWINDINFO-NEXT:  DW_CFA_restore: reg29

name:            test_allocate_sve_gpr_callee_saves
stack:
  - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2 }
  - { id: 1, stack-id: default, size: 16, alignment: 8 }
body:             |
  bb.0.entry:
    $x20 = IMPLICIT_DEF
    $x21 = IMPLICIT_DEF
    RET_ReallyLR
---
...
# +----------+
# |  lr, fp  |  // frame record
# +----------+ <- FP
# | %stack.0 |  // scalable objects
# +----------+
# |//////////|  // alignment gap
# | %stack.1 |  // not scalable
# +----------+ <- SP
# CHECK-LABEL: name: test_allocate_sve_gpr_realigned
# CHECK:       stackSize: 32

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa $w29, 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -8
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: $[[TMP:x[0-9]+]] = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: $sp = ANDXri killed $[[TMP]]
# CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_allocate_sve_gpr_realigned:
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa w29, 16
# ASM-NEXT:  .cfi_offset w30, -8
# ASM-NEXT:  .cfi_offset w29, -16
#
# ASM:        .cfi_def_cfa wsp, 16
# ASM:        .cfi_def_cfa_offset 0
# ASM-NEXT:   .cfi_restore w30
# ASM-NEXT:   .cfi_restore w29

#
# UNWINDINFO:       DW_CFA_def_cfa_offset: +16
# UNWINDINFO:       DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-NEXT:  DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT:  DW_CFA_offset: reg29 -16
#
# UNWINDINFO:       DW_CFA_def_cfa: reg31 +16
# UNWINDINFO:       DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT:  DW_CFA_restore: reg30
# UNWINDINFO-NEXT:  DW_CFA_restore: reg29


name:            test_allocate_sve_gpr_realigned
stack:
  - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2  }
  - { id: 1, stack-id: default, size: 16, alignment: 32 }
body:             |
  bb.0.entry:
    RET_ReallyLR
---
...
# +----------+
# | x20, x21 |  // callee saves
# +----------+
# | %stack.0 |  // scalable @ SP + 16b + 32 scalable bytes
# | %stack.1 |  // scalable @ SP + 16b + 16 scalable bytes
# | %stack.2 |  // scalable @ SP + 16b + 14 scalable bytes
# +----------+
# | %stack.3 |  // not scalable
# +----------+ <- SP

# CHECK-LABEL: name: test_address_sve
# CHECK:       stackSize: 32

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
# CHECK-NEXT: STR_ZXI $z0, killed $[[TMP]], 2
# CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
# CHECK-NEXT: STR_ZXI $z1, killed $[[TMP]], 1
# CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
# CHECK-NEXT: STR_PXI $p0, killed $[[TMP]], 7

# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 32

# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL:  test_address_sve:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 24 * VG
#
# ASM:       .cfi_def_cfa wsp, 32
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29
#
# UNWINDINFO:       DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT:  DW_CFA_offset: reg29 -16
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:       DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:       DW_CFA_def_cfa: reg31 +32
# UNWINDINFO:       DW_CFA_def_cfa_offset: +16
# UNWINDINFO:       DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT:  DW_CFA_restore: reg29


name:            test_address_sve
frameInfo:
  maxAlignment:  16
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 }
  - { id: 1, stack-id: scalable-vector, size: 16, alignment: 8 }
  - { id: 2, stack-id: scalable-vector, size:  2, alignment: 2 }
  - { id: 3, stack-id: default, size: 16, alignment: 8 }
body:             |
  bb.0.entry:
    liveins: $z0, $z1, $p0

    STR_ZXI $z0, %stack.0, 0
    STR_ZXI $z1, %stack.1, 0
    STR_PXI $p0, %stack.2, 0

    RET_ReallyLR
---
...
# +-----------+
# | x20, x21  |  // callee saves
# |  lr, fp   |  // frame record
# +-----------+ <- FP
# | %stack.0  |  // scalable @ FP - 16 scalable bytes
# | %stack.1  |  // scalable @ FP - 32 scalable bytes
# | %stack.2  |  // scalable @ FP - 34 scalable bytes
# +-----------+
# | %stack.3  |  // not scalable
# +-----------+ <- SP

# CHECK-LABEL: name: test_address_sve_fp
# CHECK:       stackSize: 32

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa $w29, 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -8
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0

# CHECK-NEXT: STR_ZXI $z0, $fp, -1
# CHECK-NEXT: STR_ZXI $z1, $fp, -2
# CHECK-NEXT: STR_PXI $p0, $fp, -17

# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
# CHECK:      $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_sve_fp:
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa w29, 16
# ASM-NEXT:  .cfi_offset w30, -8
# ASM-NEXT:  .cfi_offset w29, -16
#
# ASM:       .cfi_def_cfa wsp, 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w30
# ASM-NEXT:  .cfi_restore w29
#
# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO:      DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
#
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +16
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg30
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name:            test_address_sve_fp
frameInfo:
  maxAlignment:  16
  isFrameAddressTaken: true
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 }
  - { id: 1, stack-id: scalable-vector, size: 16, alignment: 8 }
  - { id: 2, stack-id: scalable-vector, size:  2, alignment: 2 }
  - { id: 3, stack-id: default, size: 16, alignment: 8 }
body:             |
  bb.0.entry:
    liveins: $z0, $z1, $p0

    STR_ZXI $z0, %stack.0, 0
    STR_ZXI $z1, %stack.1, 0
    STR_PXI $p0, %stack.2, 0

    RET_ReallyLR
---
...
# +-----------+
# | %fstack.1 |  // stack arg @ SP + 16 scalable bytes + 32 bytes.
# +-----------+
# |callee save|  // register saved as scratch reg.
# +-----------+
# | %stack.0  |  // vector of 16 scalable bytes
# +---------- +
# | %stack.1  |  // not scalable, 16 bytes
# +-----------+ <- SP
# CHECK-LABEL: name: test_stack_arg_sve
# CHECK:       stackSize: 32

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16

# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $[[TMP:x[0-9]+]] = ADDVL_XXI $sp, 1
# CHECK-NEXT: $x0 = LDRXui killed $[[TMP]], 4

# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 1
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 32
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_stack_arg_sve:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 8 * VG
#
# ASM:       .cfi_def_cfa wsp, 32
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +32
# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name:             test_stack_arg_sve
fixedStack:
  - { id: 0, stack-id: default, size: 16, alignment: 16, offset: 0 }
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 }
  - { id: 1, stack-id: default, size: 16, alignment: 16 }
body:             |
  bb.0.entry:
    liveins: $x0

    $x0 = LDRXui %fixed-stack.0, 0
    RET_ReallyLR
---
...
# Test that the address to access an SVE data vector at an offset that
# does not fit its immediate, is correctly materialized.
# +----------+
# |calleesave|  // register saved as scratch reg.
# +----------+
# | %stack.0 |  // one SVE data object @ SP + 256 scalable bytes.
# |::::::::::|
# |:        :|
# |:%stack.1:|  // Large object
# |:        :|
# |::::::::::|
# +----------+ <- SP
# CHECK-LABEL: name: test_address_sve_out_of_range
# CHECK:       stackSize: 16

# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x02, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x04, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x06, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0a, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0c, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0e, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x88, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK-NEXT: $[[TMP2:x[0-9]+]] = ADDVL_XXI $sp, 1
# CHECK-NEXT: STR_ZXI $z0, killed $[[TMP2]], 255

# CHECK-NEXT: $[[TMP2:x[0-9]+]] = ADDPL_XXI $sp, 1
# CHECK-NEXT: STR_PXI $p0, killed $[[TMP2]], 255

# CHECK:      $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x90, 0x0e, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x98, 0x0c, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xa0, 0x0a, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xa8, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xb0, 0x06, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xb8, 0x04, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xc0, 0x02, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xc8, 0x00, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 9
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_sve_out_of_range:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x02, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 256 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x04, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 512 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x06, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 768 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1024 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0a, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1280 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0c, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1536 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x0e, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1792 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x80, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 2048 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x88, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 2056 * VG
#
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x90, 0x0e, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1808 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x98, 0x0c, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1560 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xa0, 0x0a, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1312 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xa8, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 1064 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xb0, 0x06, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 816 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xb8, 0x04, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 568 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xc0, 0x02, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 320 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xc8, 0x00, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 72 * VG
# ASM:        .cfi_def_cfa wsp, 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +256, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +512, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +768, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1024, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1280, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1536, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1792, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +2048, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +2056, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1808, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1560, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1312, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +1064, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +816, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +568, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +320, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +72, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +16
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name:            test_address_sve_out_of_range
frameInfo:
  maxAlignment:  16
stack:
  - { id: 0, stack-id: scalable-vector, size:   16, alignment: 16 }
  - { id: 1, stack-id: scalable-vector, size: 3584, alignment: 16 }
  - { id: 2, stack-id: scalable-vector, size:  512, alignment: 16 }

body:             |
  bb.0.entry:
    liveins: $z0, $p0

    STR_ZXI $z0, %stack.0, 0
    STR_PXI $p0, %stack.1, 0

    RET_ReallyLR
---
...
# Test that non-SVE objects are accessed from BP when there are
# variable length arrays, because it will be more expensive to
# access from the FP when there are also SVE objects on the stack.
#
# +----------+ <- FP
# | %stack.0 |  // 16 scalable bytes
# +----------+ <- @FP - 16 scalable bytes
# | %stack.1 |  // 16 bytes
# +----------+ <- @BP
# : %stack.2 :  // variable length
# +----------+ <- SP

# CHECK-LABEL: name: test_address_gpr_vla
# CHECK: bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -4
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 32
# CHECK-NEXT: frame-setup STRXui killed $x19, $sp, 2
# CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa $w29, 32
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w19, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -24
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -32
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: $x19 = ADDXri $sp, 0, 0
# CHECK-NEXT: STRXui $xzr, $x19, 0
# CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 32
# CHECK-NEXT: $x19 = frame-destroy LDRXui $sp, 2
# CHECK-NEXT: early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 4
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w19
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_gpr_vla:
# ASM:       .cfi_def_cfa_offset 32
# ASM:       .cfi_def_cfa w29, 32
# ASM-NEXT:  .cfi_offset w19, -16
# ASM-NEXT:  .cfi_offset w30, -24
# ASM-NEXT:  .cfi_offset w29, -32
#
# ASM:       .cfi_def_cfa wsp, 32
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w19
# ASM-NEXT:  .cfi_restore w30
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +32
# UNWINDINFO:      DW_CFA_def_cfa: reg29 +32
# UNWINDINFO-NEXT: DW_CFA_offset: reg19 -16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -24
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -32
#
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +32
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg19
# UNWINDINFO-NEXT: DW_CFA_restore: reg30
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name:            test_address_gpr_vla
frameInfo:
  maxAlignment:  16
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 }
  - { id: 1, stack-id: default, size: 16, alignment: 8 }
  - { id: 2, stack-id: default, type: variable-sized }
body:             |
  bb.0.entry:
    liveins: $xzr

    STRXui $xzr, %stack.1, 0

    RET_ReallyLR
---
...
# CHECK-LABEL: name: save_restore_pregs_sve
# CHECK:      $sp = frame-setup STRXpre killed $fp, $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK:      $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      frame-setup STR_PXI killed $p6, $sp, 5
# CHECK:      frame-setup STR_PXI killed $p5, $sp, 6
# CHECK:      frame-setup STR_PXI killed $p4, $sp, 7
# CHECK:      $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK:      $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $p6 = frame-destroy LDR_PXI $sp, 5
# CHECK:      $p5 = frame-destroy LDR_PXI $sp, 6
# CHECK:      $p4 = frame-destroy LDR_PXI $sp, 7
# CHECK:      $sp = frame-destroy ADDVL_XXI $sp, 1
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: early-clobber $sp, $fp = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.4)
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR

#
# ASM-LABEL: save_restore_pregs_sve:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 8 * VG
#
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
# ASM:       .cfi_def_cfa wsp, 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:         DW_CFA_def_cfa_offset: +16
# UNWINDINFO:         DW_CFA_offset: reg29 -16
# UNWINDINFO:         DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:         DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:         DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:         DW_CFA_def_cfa: reg31 +16
# UNWINDINFO:         DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT:    DW_CFA_restore: reg29

name: save_restore_pregs_sve
stack:
  - { id: 0, stack-id: default, size: 32, alignment: 16 }
body:             |
  bb.0.entry:

    $p4 = IMPLICIT_DEF
    $p5 = IMPLICIT_DEF
    $p6 = IMPLICIT_DEF

    RET_ReallyLR
---
...
# CHECK-LABEL: name: save_restore_zregs_sve
# CHECK:      $sp = frame-setup STRXpre killed $fp, $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup STR_ZXI killed $z10, $sp, 0
# CHECK-NEXT: frame-setup STR_ZXI killed $z9, $sp, 1
# CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x49, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4a, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK:      $sp  = frame-destroy ADDXri $sp, 32, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $z10 = frame-destroy LDR_ZXI $sp, 0
# CHECK-NEXT: $z9  = frame-destroy LDR_ZXI $sp, 1
# CHECK-NEXT: $z8  = frame-destroy LDR_ZXI $sp, 2
# CHECK-NEXT: $sp  = frame-destroy ADDVL_XXI $sp, 3
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z8
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z9
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z10
# CHECK-NEXT: $sp, $fp = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: save_restore_zregs_sve:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
# ASM:       .cfi_escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d8  @ cfa - 16 - 8 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x49, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d9  @ cfa - 16 - 16 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4a, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d10  @ cfa - 16 - 24 * VG
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 24 * VG
#
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
# ASM:       .cfi_def_cfa wsp, 16
# ASM-NEXT:  .cfi_restore z8
# ASM-NEXT:  .cfi_restore z9
# ASM-NEXT:  .cfi_restore z10
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_expression: reg72 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg73 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg74 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +16
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg104
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg105
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg106
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name: save_restore_zregs_sve
stack:
  - { id: 0, stack-id: default, size: 32, alignment: 16 }
body:             |
  bb.0.entry:

    $z8 = IMPLICIT_DEF
    $z9 = IMPLICIT_DEF
    $z10 = IMPLICIT_DEF

    RET_ReallyLR
---
...
# Test allocation/deallocation of the stack frame together with the
# saving/restoring of callee save registers. Fixed-stack objects
# are allocated before the callee-saves.
# This also adds some non-SVE callee-saves, to ensure that those are
# paired correctly.
#
# CHECK-LABEL: name: save_restore_sve
# CHECK:      $sp = frame-setup STPXpre killed ${{[a-z0-9]+}}, killed $x21, $sp, -4
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 32
# CHECK-NEXT: frame-setup STPXi killed $x20, killed $x19, $sp, 2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w19, -8
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w20, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w21, -24
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -32

# CHECK:      $sp = frame-setup ADDVL_XXI $sp, -18
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x90, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      frame-setup STR_PXI killed $p15, $sp, 4
# CHECK:      frame-setup STR_PXI killed $p14, $sp, 5
# CHECK:      frame-setup STR_PXI killed $p5, $sp, 14
# CHECK:      frame-setup STR_PXI killed $p4, $sp, 15
# CHECK:      frame-setup STR_ZXI killed $z23, $sp, 2
# CHECK:      frame-setup STR_ZXI killed $z22, $sp, 3
# CHECK:      frame-setup STR_ZXI killed $z9, $sp, 16
# CHECK:      frame-setup STR_ZXI killed $z8, $sp, 17
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x48, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x49, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4a, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4b, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x60, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4c, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x58, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4d, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x50, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4e, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x48, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4f, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x40, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0e, 0x8f, 0x00, 0x11, 0xc0, 0x00, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK:      $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $sp = frame-destroy ADDVL_XXI $sp, 1
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x90, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK:      $p15 = frame-destroy LDR_PXI $sp, 4
# CHECK:      $p14 = frame-destroy LDR_PXI $sp, 5
# CHECK:      $p5 = frame-destroy LDR_PXI $sp, 14
# CHECK:      $p4 = frame-destroy LDR_PXI $sp, 15
# CHECK:      $z23 = frame-destroy LDR_ZXI $sp, 2
# CHECK:      $z22 = frame-destroy LDR_ZXI $sp, 3
# CHECK:      $z9 = frame-destroy LDR_ZXI $sp, 16
# CHECK:      $z8 = frame-destroy LDR_ZXI $sp, 17
# CHECK:      $sp = frame-destroy ADDVL_XXI $sp, 18
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 32
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z8
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z9
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z10
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z11
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z12
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z13
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z14
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z15

# CHECK: $x20, $x19 = frame-destroy LDPXi $sp, 2
# CHECK: $sp, ${{[a-z0-9]+}}, $x21 = frame-destroy LDPXpost $sp, 4
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w19
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w20
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w21
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29

# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: save_restore_sve:
# ASM:       .cfi_def_cfa_offset 32
# ASM:       .cfi_offset w19, -8
# ASM-NEXT:  .cfi_offset w20, -16
# ASM-NEXT:  .cfi_offset w21, -24
# ASM-NEXT:  .cfi_offset w29, -32
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x90, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 144 * VG
# ASM:       .cfi_escape 0x10, 0x48, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d8 @ cfa - 32 - 8 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x49, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d9 @ cfa - 32 - 16 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4a, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d10 @ cfa - 32 - 24 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4b, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x60, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d11 @ cfa - 32 - 32 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4c, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x58, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d12 @ cfa - 32 - 40 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4d, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x50, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d13 @ cfa - 32 - 48 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4e, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x48, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d14 @ cfa - 32 - 56 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4f, 0x0a, 0x11, 0x60, 0x22, 0x11, 0x40, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d15 @ cfa - 32 - 64 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 152 * VG
# ASM:       .cfi_escape 0x0f, 0x0e, 0x8f, 0x00, 0x11, 0xc0, 0x00, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 64 + 152 * VG
#
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 152 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x90, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 144 * VG
# ASM:       .cfi_def_cfa wsp, 32
# ASM-NEXT:  .cfi_restore z8
# ASM-NEXT:  .cfi_restore z9
# ASM-NEXT:  .cfi_restore z10
# ASM-NEXT:  .cfi_restore z11
# ASM-NEXT:  .cfi_restore z12
# ASM-NEXT:  .cfi_restore z13
# ASM-NEXT:  .cfi_restore z14
# ASM-NEXT:  .cfi_restore z15
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w19
# ASM-NEXT:  .cfi_restore w20
# ASM-NEXT:  .cfi_restore w21
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +32
# UNWINDINFO:      DW_CFA_offset: reg19 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg20 -16
# UNWINDINFO-NEXT: DW_CFA_offset: reg21 -24
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -32
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +144, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_expression: reg72 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg73 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg74 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg75 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -32, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg76 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -40, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg77 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -48, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg78 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -56, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg79 DW_OP_consts -32, DW_OP_plus, DW_OP_consts -64, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +152, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +64, DW_OP_plus, DW_OP_consts +152, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +152, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +144, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +32
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg104
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg105
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg106
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg107
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg108
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg109
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg110
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg111
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg19
# UNWINDINFO-NEXT: DW_CFA_restore: reg20
# UNWINDINFO-NEXT: DW_CFA_restore: reg21
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name: save_restore_sve
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 }
  - { id: 1, stack-id: default, size: 32, alignment: 16 }
body:             |
  bb.0.entry:

    $z8_z9_z10_z11   = IMPLICIT_DEF
    $z12_z13_z14_z15 = IMPLICIT_DEF
    $z16_z17_z18_z19 = IMPLICIT_DEF
    $z20_z21_z22_z23 = IMPLICIT_DEF
    $z24_z25_z26_z27 = IMPLICIT_DEF
    $z28_z29_z30_z31 = IMPLICIT_DEF
    $p4 = IMPLICIT_DEF
    $p5 = IMPLICIT_DEF
    $p6 = IMPLICIT_DEF
    $p7 = IMPLICIT_DEF
    $p8 = IMPLICIT_DEF
    $p9 = IMPLICIT_DEF
    $p10 = IMPLICIT_DEF
    $p11 = IMPLICIT_DEF
    $p12 = IMPLICIT_DEF
    $p13 = IMPLICIT_DEF
    $p14 = IMPLICIT_DEF
    $p15 = IMPLICIT_DEF

    $x19 = IMPLICIT_DEF
    $x20 = IMPLICIT_DEF
    $x21 = IMPLICIT_DEF

    RET_ReallyLR
---
...
# Test allocation/deallocation of the stack frame together with the
# saving/restoring of callee save registers. Fixed-stack objects
# are allocated before the callee-saves.
#
# CHECK-LABEL: name: save_restore_sve_realign
# CHECK:      $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa $w29, 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -8
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -18
# CHECK-NEXT: STR_PXI killed $p15, $sp, 4
# CHECK-NEXT: STR_PXI killed $p14, $sp, 5
# CHECK:      STR_PXI killed $p5, $sp, 14
# CHECK-NEXT: STR_PXI killed $p4, $sp, 15
# CHECK-NEXT: STR_ZXI killed $z23, $sp, 2
# CHECK-NEXT: STR_ZXI killed $z22, $sp, 3
# CHECK:      STR_ZXI killed $z9, $sp, 16
# CHECK-NEXT: STR_ZXI killed $z8, $sp, 17
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x49, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4a, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4b, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x60, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4c, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x58, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4d, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x50, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4e, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x48, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x4f, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x40, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: $[[TMP:x[0-9]+]] = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: $sp = ANDXri killed $[[TMP]]

# CHECK:      $sp = frame-destroy ADDVL_XXI $fp, -18
# CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 4
# CHECK-NEXT: $p14 = frame-destroy LDR_PXI $sp, 5
# CHECK:      $p5 = frame-destroy LDR_PXI $sp, 14
# CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 15
# CHECK-NEXT: $z23 = frame-destroy LDR_ZXI $sp, 2
# CHECK-NEXT: $z22 = frame-destroy LDR_ZXI $sp, 3
# CHECK:      $z9 = frame-destroy LDR_ZXI $sp, 16
# CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 17
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z8
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z9
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z10
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z11
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z12
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z13
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z14
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z15
# CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: save_restore_sve_realign:
# ASM:       .cfi_def_cfa_offset 16
# ASM:       .cfi_def_cfa w29, 16
# ASM-NEXT:  .cfi_offset w30, -8
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d8  @ cfa - 16 - 8 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x49, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x70, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d9  @ cfa - 16 - 16 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4a, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x68, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d10  @ cfa - 16 - 24 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4b, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x60, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d11  @ cfa - 16 - 32 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4c, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x58, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d12  @ cfa - 16 - 40 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4d, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x50, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d13  @ cfa - 16 - 48 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4e, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x48, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d14  @ cfa - 16 - 56 * VG
# ASM-NEXT:  .cfi_escape 0x10, 0x4f, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x40, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d15  @ cfa - 16 - 64 * VG
#
# ASM:       .cfi_restore z8
# ASM-NEXT:  .cfi_restore z9
# ASM-NEXT:  .cfi_restore z10
# ASM-NEXT:  .cfi_restore z11
# ASM-NEXT:  .cfi_restore z12
# ASM-NEXT:  .cfi_restore z13
# ASM-NEXT:  .cfi_restore z14
# ASM-NEXT:  .cfi_restore z15
# ASM:       .cfi_def_cfa wsp, 16
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w30
# ASM-NEXT:  .cfi_restore w29
#
# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO:      DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
# UNWINDINFO:      DW_CFA_expression: reg72 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg73 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg74 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg75 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -32, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg76 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -40, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg77 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -48, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg78 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -56, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_expression: reg79 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -64, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_restore_extended: reg104
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg105
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg106
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg107
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg108
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg109
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg110
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg111
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +16
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg30
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name: save_restore_sve_realign
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 }
  - { id: 1, stack-id: default, size: 16, alignment: 32 }
body:             |
  bb.0.entry:

    $z8_z9_z10_z11   = IMPLICIT_DEF
    $z12_z13_z14_z15 = IMPLICIT_DEF
    $z16_z17_z18_z19 = IMPLICIT_DEF
    $z20_z21_z22_z23 = IMPLICIT_DEF
    $z24_z25_z26_z27 = IMPLICIT_DEF
    $z28_z29_z30_z31 = IMPLICIT_DEF
    $p4 = IMPLICIT_DEF
    $p5 = IMPLICIT_DEF
    $p6 = IMPLICIT_DEF
    $p7 = IMPLICIT_DEF
    $p8 = IMPLICIT_DEF
    $p9 = IMPLICIT_DEF
    $p10 = IMPLICIT_DEF
    $p11 = IMPLICIT_DEF
    $p12 = IMPLICIT_DEF
    $p13 = IMPLICIT_DEF
    $p14 = IMPLICIT_DEF
    $p15 = IMPLICIT_DEF

    RET_ReallyLR
---
# Frame layout should be:
# +---------------------+ <- Old SP
# | callee save z8      |@ -16
# | callee save z23     |@ -32
# | callee save p4      |@ -34
# | callee save p15     |@ -48
# | id #0 (size 32)     |@ -80
# | id #1 (size 4)      |@ -84
# | id #2 (size 16)     |@ -112
# | id #3 (size 2)      |@ -114
# | id #4 (size 16)     |@ -144
# | id #5 (size 2)      |@ -146
# +- - - - - - - - - - -+ <- New SP @-160
# CHECK-LABEL: name: frame_layout
# CHECK:       stack:
# CHECK:        - { id: 0, name: '', type: default, offset: -80, size: 32, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 1, name: '', type: default, offset: -84, size: 4, alignment: 2,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 2, name: '', type: default, offset: -112, size: 16, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 3, name: '', type: default, offset: -114, size: 2, alignment: 2,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 4, name: '', type: spill-slot, offset: -144, size: 16, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 5, name: '', type: spill-slot, offset: -146, size: 2, alignment: 2,
# CHECK-NEXT:       stack-id: scalable-vector,
# CHECK:        - { id: 6, name: '', type: spill-slot, offset: -16, size: 16, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector, callee-saved-register: '$z8',
# CHECK:        - { id: 7, name: '', type: spill-slot, offset: -32, size: 16, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector, callee-saved-register: '$z23',
# CHECK:        - { id: 8, name: '', type: spill-slot, offset: -34, size: 2, alignment: 2,
# CHECK-NEXT:       stack-id: scalable-vector, callee-saved-register: '$p4',
# CHECK:        - { id: 9, name: '', type: spill-slot, offset: -36, size: 2, alignment: 2,
# CHECK-NEXT:       stack-id: scalable-vector, callee-saved-register: '$p15',
# CHECK:        - { id: 10, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16,
# CHECK-NEXT:       stack-id: default, callee-saved-register: '$fp',
#
# CHECK:      bb.0.entry:
# CHECK-NEXT: liveins:
# CHECK-NEXT: {{  $}}
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
# CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w29, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: STR_PXI killed $p15, $sp, 6
# CHECK-NEXT: STR_PXI killed $p4, $sp, 7
# CHECK-NEXT: STR_ZXI killed $z23, $sp, 1
# CHECK-NEXT: STR_ZXI killed $z8, $sp, 2
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -7
# CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xd0, 0x00, 0x92, 0x2e, 0x00, 0x1e, 0x22

# CHECK:      $sp = frame-destroy ADDVL_XXI $sp, 7
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22
# CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 6
# CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 7
# CHECK-NEXT: $z23 = frame-destroy LDR_ZXI $sp, 1
# CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 2
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $wsp, 16
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $z8
# CHECK-NEXT: early-clobber $sp, $fp = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.10)
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
# CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w29
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: frame_layout:
# ASM:       .cfi_def_cfa_offset 16
# ASM-NEXT:  .cfi_offset w29, -16
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
# ASM:       .cfi_escape 0x10, 0x48, 0x0a, 0x11, 0x70, 0x22, 0x11, 0x78, 0x92, 0x2e, 0x00, 0x1e, 0x22 // $d8  @ cfa - 16 - 8 * VG
# ASM:       .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xd0, 0x00, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 80 * VG
#
# ASM:       .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
# ASM:       .cfi_def_cfa wsp, 16
# ASM-NEXT:  .cfi_restore z8
# ASM:       .cfi_def_cfa_offset 0
# ASM-NEXT:  .cfi_restore w29

# UNWINDINFO:      DW_CFA_def_cfa_offset: +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_expression: reg72 DW_OP_consts -16, DW_OP_plus, DW_OP_consts -8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +80, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
#
# UNWINDINFO:      DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO:      DW_CFA_def_cfa: reg31 +16
# UNWINDINFO-NEXT: DW_CFA_restore_extended: reg104
# UNWINDINFO:      DW_CFA_def_cfa_offset: +0
# UNWINDINFO-NEXT: DW_CFA_restore: reg29

name: frame_layout
stack:
  - { id: 0, type: default,    size:  32, alignment: 16, stack-id: scalable-vector }
  - { id: 1, type: default,    size:   4, alignment:  2, stack-id: scalable-vector }
  - { id: 2, type: default,    size:  16, alignment: 16, stack-id: scalable-vector }
  - { id: 3, type: default,    size:   2, alignment:  2, stack-id: scalable-vector }
  - { id: 4, type: spill-slot, size:  16, alignment: 16, stack-id: scalable-vector }
  - { id: 5, type: spill-slot, size:   2, alignment:  2, stack-id: scalable-vector }
body:             |
  bb.0.entry:

    ; Trigger some callee saves
    $z8  = IMPLICIT_DEF
    $z23 = IMPLICIT_DEF
    $p4  = IMPLICIT_DEF
    $p15 = IMPLICIT_DEF

    RET_ReallyLR

---
# Make sure we account for the offset between the fp and the sve area, if it exists.
# FIXME: Should there be an offset?
# CHECK-LABEL: name: fp_relative_index_with_float_save
# CHECK:        - { id: 0, name: '', type: default, offset: -16, size: 16, alignment: 16,
# CHECK-NEXT:       stack-id: scalable-vector
# CHECK:        - { id: 1, name: '', type: default, offset: -64, size: 16, alignment: 32,
# CHECK-NEXT:      stack-id: default
# CHECK:        - { id: 2, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8,
# CHECK-NEXT:      stack-id: default, callee-saved-register: '$lr'
# CHECK:        - { id: 3, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8,
# CHECK-NEXT:      stack-id: default, callee-saved-register: '$fp'
# CHECK:        - { id: 4, name: '', type: spill-slot, offset: -32, size: 8, alignment: 16,
# CHECK-NEXT:      stack-id: default, callee-saved-register: '$d8'

# CHECK: $x8 = SUBXri $fp, 16, 0
# CHECK: STR_ZXI $z0, killed $x8, -1

name: fp_relative_index_with_float_save
stack:
  - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 }
  - { id: 1, stack-id: default, size: 16, alignment: 32 }
frameInfo:
  maxAlignment:  16
  isFrameAddressTaken: true
body:             |
  bb.0.entry:
    liveins: $z0

    $d8 = IMPLICIT_DEF

    STR_ZXI $z0, %stack.0, 0

    RET_ReallyLR
---
